RDS(PostgreSQL)のトランザクションログ(WAL)へCDCに必要な内容を出力する
はじめに
こんにちは、データインテグレーション部の近藤です。
今回は、RDSにおいて、PostgreSQLの設定のwal_levelをreplicaからlogicalに変更することにより、PostgreSQLのトランザクションログ(WAL)へChange Data Capture(以下、CDC)に必要を内容を出力させる設定方法をご紹介します。
wal_levelを設定することになった経緯
データベース移行サービスであるAmazon Database Migration Service(以下、DMS)には、継続的なレプリケーション機能(差分更新)の機能があります。この動作テストを行おうと、ソースDBをRDSのPostgreSQL、ターゲットDBをS3としてタスクを作り動かしました。ソースDBのPostgreSQLにデータを逐次INSERTし、それに伴いターゲットDBであるS3にオブジェクトが作られていくことを期待したのですが、なぜか作られませんでした。
原因は、PostgreSQLの設定項目のwal_levelの値が、正しく設定されていなかったためです。DMSがCDCを行うには、ソースDBの更新情報がDMSの理解できるフォーマットでトランザクションログ(WAL)に出力されている必要があります。そのためには、wal_levelの値がlogicalでなければいけないのですが、デフォルトのreplicaのままでした。そのため、CDCに必要な更新情報がトランザクションログ(WAL)に出力されず、DMSがソースDBの更新を検知できなかったわけです。
このwal_levelの設定は通常postgres.confを編集するのですが、RDSではpostgres.confの設定をパラメーターグループで行わねばならず、さらにwal_levelという項目がパラメーターグループになく別の項目の設定が必要だったために、少しはまりました。
PostgreSQLのトランザクションログ(WAL)とロジカルデコーディング
ここでPostgreSQLのトランザクションログであるWALと、wal_levelの設定値のlogical(ロジカルデコーディング)について整理します。
WAL
WALとはWrite Ahead Logging(ログ先行書き込み)の略で、一般的にはトランザクションログと呼ばれるものです。PostgreSQLに対して行われた更新操作を記録します。
ロジカルデコーディング
ロジカルデコーディングというのは、PostgreSQL9.4から採用された機能で、物理的な更新情報しか記録されていなかったWALに論理的な更新情報を記録させるというものです。これにより、DBに対する更新操作が、どのファイルのどのブロックに何を書き込んだといった物理的な情報のみではなく、どのテーブルにどのようなレコードが書き込まれたかという論理的な情報として記録されます。これによって、CDCが可能になります。
これの記録内容を指定するのがwal_levelの値で、RDSのPostgreSQLのデフォルトではreplicaになっています。
RDSのPostgreSQLのwal_level設定手順
wal_levelをlogicalに変更するには、RDSのコンソール画面において、対象インスタンスが適用しているパラメーターグループのrds.logical_replicationを1に変更して、RDSインスタンスを再起動します。これにより、wal_levelが、replicaからlogicalに変更されます。
以下に、手順をみていきましょう。
①wal_levelのデフォルト値の確認
デフォルトの状態では、wal_levelはreplicaです。
dbtest=> SELECT name, setting FROM pg_settings WHERE name='wal_level'; name | setting -------+--------- wal_level | replica (1 row)
wal_levelがreplicaの状態では、テーブルにデータをINSERTしてみますが、その情報はloical decodingで参照しても取得されません。
②パラメータグループのrds.logical_replicationを変更
対象のRDSインスタンスが適用しているパラメータグループを選択し、編集します。このときパラメータグループが、defaultのもの(default.postgres9.X)だと変更できません。その場合は、あらたにパラメータグループを作成してください。
rds.logical_replicationの値を0から1に変更します。
③変更結果の確認
RDSを再起動すると、wal_levelがlogialに変更されています。
dbtest=> SELECT name, setting FROM pg_settings WHERE name='wal_level'; name | setting -----------+--------- wal_level | logical (1 row)